home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -serious- / archivers / xpk / xpk_source / xpkmaster / seek.c < prev    next >
C/C++ Source or Header  |  1999-06-14  |  5KB  |  173 lines

  1. #ifndef XPKMASTER_SEEK_C
  2. #define XPKMASTER_SEEK_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        seek.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: seek.c 1.0 (30.10.1998)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    Implementation of XpkSeek
  12.  
  13.  1.0   30.10.98 : first version
  14. */
  15.  
  16. #include <exec/memory.h>
  17. #include <proto/exec.h>
  18. #include <proto/xpkmaster.h>
  19. #include "xpkmaster.h"
  20.  
  21. /* get chunk header and and seek data when necessary */
  22. XPK_ALLINONE LONG addseek(struct XpkBuffer *xbuf)
  23. {
  24.   LONG ulen;
  25.   struct SeekDataList *sdl;
  26.  
  27.   if(!(xbuf->xb_Flags & XMF_SEEK))
  28.     return 0;
  29.  
  30.   ulen = xbuf->xb_UCur;
  31.  
  32.   /* check if already included */
  33.   sdl = xbuf->xb_SeekDataList;
  34.   while(sdl && sdl->sdl_Next)
  35.     sdl = sdl->sdl_Next;
  36.   if(sdl && sdl->sdl_Data[sdl->sdl_Used-1].sd_ULen >= ulen)
  37.     return 0; /* already done, so we quit */
  38.   if(!sdl || sdl->sdl_Used == SEEKENTRYNUM)
  39.   {
  40.     struct SeekDataList *sdl2;
  41.     if(!(sdl2 = (struct SeekDataList *)
  42.     AllocMem(sizeof(struct SeekDataList), MEMF_CLEAR|MEMF_PUBLIC)))
  43.       return (xbuf->xb_Result = XPKERR_NOMEM);
  44.     if(!xbuf->xb_SeekDataList)
  45.       xbuf->xb_SeekDataList = sdl2;
  46.     else
  47.       sdl->sdl_Next = sdl2;
  48.     sdl = sdl2;
  49.   }
  50.  
  51.   sdl->sdl_Data[sdl->sdl_Used].sd_FilePos = xbuf->xb_InBufferPos;
  52.   sdl->sdl_Data[sdl->sdl_Used].sd_ULen = ulen;
  53.   sdl->sdl_Data[(sdl->sdl_Used)++].sd_CLen = xbuf->xb_CCur;
  54.  
  55. #ifdef DEBUG
  56.   DebugRunTime("addseek: added entry (pos %ld, ulen %ld)",
  57.   xbuf->xb_InBufferPos, ulen);
  58. #endif
  59.  
  60.   return 0;
  61. }
  62.  
  63. XPK_ALLINONE void freeseek(struct XpkBuffer *xbuf)
  64. {
  65.   struct SeekDataList *sdl, *sdl2;
  66.   
  67.   sdl = xbuf->xb_SeekDataList;
  68.   while(sdl)
  69.   {
  70.     sdl2 = sdl->sdl_Next;
  71.     FreeMem(sdl, sizeof(struct SeekDataList));
  72.     sdl = sdl2;
  73.   }
  74.   xbuf->xb_SeekDataList = 0;
  75. }
  76.  
  77. LONG doseek(struct XpkBuffer *xbuf, LONG pos)
  78. {
  79.   LONG ulen, clen;
  80.   XpkChunkHeader *lochdr = &(xbuf->xb_Headers.h_Loc);
  81.   struct SeekDataList *sdl;
  82.  
  83.   if(pos > xbuf->xb_Fib.xf_ULen)
  84.     return XPKERR_BADPARAMS;
  85.  
  86.   if(xbuf->xb_Format == XPKMODE_UPUP)
  87.   {
  88.     xbuf->xb_Flags &= ~XMF_EOF;
  89.  
  90.     if(!(hookread(xbuf, XIO_SEEK, 0, pos - xbuf->xb_InBufferPos)))
  91.       return xbuf->xb_Result;
  92.  
  93.     xbuf->xb_Fib.xf_CCur = xbuf->xb_Fib.xf_UCur = xbuf->xb_InBufferPos;
  94.     xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  95.     DEFAULTCHUNKSIZE) + XPK_MARGIN;
  96.  
  97.     return 0;
  98.   }
  99.  
  100.   for(sdl = xbuf->xb_SeekDataList; sdl; sdl = sdl->sdl_Next)
  101.   {
  102.     LONG i;
  103.     for(i = 0; i < sdl->sdl_Used; ++i)
  104.     {
  105.       if(sdl->sdl_Data[i].sd_ULen > pos)
  106.       {
  107.         if(!(hookread(xbuf, XIO_SEEK, 0, sdl->sdl_Data[i].sd_FilePos -
  108.         xbuf->xb_Headers.h_LocSize - xbuf->xb_InBufferPos)))
  109.       return xbuf->xb_Result;
  110.         if(!(hookread(xbuf, XIO_READ, lochdr, xbuf->xb_Headers.h_LocSize)))
  111.           return xbuf->xb_Result;
  112.         getUClen(xbuf, &ulen, &clen);
  113.         xbuf->xb_UCur = sdl->sdl_Data[i].sd_ULen - ulen;
  114.         xbuf->xb_CCur = sdl->sdl_Data[i].sd_CLen - clen;
  115.         updatefib(xbuf);
  116.         return (LONG) (pos - xbuf->xb_Fib.xf_UCur);
  117.       }
  118.     }
  119.   }
  120.  
  121.   /* this is called when need a forward seek and we do not have the seek
  122.      entries */
  123.   while(xbuf->xb_UCur <= pos)
  124.   {
  125.     if(lochdr->xch_Word.xchw_Type == XPKCHUNK_END)
  126.       return XPKERR_BADPARAMS;
  127.  
  128.     getUClen(xbuf, &ulen, &clen);
  129.     if(!(hookread(xbuf, XIO_SEEK, 0, ROUNDLONG(clen))))
  130.       return xbuf->xb_Result;
  131.     if(!(hookread(xbuf, XIO_READ, lochdr, xbuf->xb_Headers.h_LocSize)))
  132.       return xbuf->xb_Result;
  133.     if(updatefib(xbuf))
  134.       return xbuf->xb_Result;
  135.   }
  136.   return (LONG) (pos - xbuf->xb_Fib.xf_UCur);
  137. }
  138.  
  139. /**************************************************************************
  140.  *
  141.  *   XpkSeek() - move around on a compressed file
  142.  *
  143.  */
  144.  
  145. /* Return codes < 0 are error codes. Codes >= 0 are file position */
  146. ASM(LONG) LIBXpkSeek(REG(a0, struct XpkBuffer *xbuf), REG(d0, LONG dist),
  147.     REG(d1, LONG mode))
  148. {
  149.   LONG err = XPKERR_BADPARAMS;
  150.  
  151.   if((xbuf->xb_Format != XPKMODE_UPSTD && xbuf->xb_Format != XPKMODE_UPUP) ||
  152.   (xbuf->xb_SubInfo->xi_Flags & (XPKIF_NOSEEK|XPKIF_PREREADHDR)))
  153.     err = XPKERR_NOFUNC;
  154.   else if(xbuf->xb_Flags & XMF_SEEK)
  155.   {
  156.     switch(mode)
  157.     {
  158.     case XPKSEEK_CURRENT: err = doseek(xbuf, xbuf->xb_Fib.xf_UCur + dist); break;
  159.     case XPKSEEK_BEGINNING: err = doseek(xbuf, dist); break;
  160.     case XPKSEEK_END: err = doseek(xbuf, xbuf->xb_Fib.xf_ULen + dist); break;
  161. /*  default: err = XPKERR_BADPARAMS; break; */
  162.     }
  163. #ifdef DEBUG
  164.   DebugRunTime("XpkSeek: position after seek (pos %ld, ulen %ld)",
  165.   xbuf->xb_InBufferPos, xbuf->xb_Fib.xf_UCur);
  166. #endif
  167.   }
  168.  
  169.   return err;
  170. }
  171.  
  172. #endif /* XPKMASTER_SEEK_C */
  173.